﻿#include "tcpclient.h"
#include "system/systemlogfile.h"
#include <QDebug>
#include <QNetworkProxy>

namespace Common {

	TcpClient::TcpClient(QObject *parent)
		: QObject(parent)
		, m_tcpSocket(new QTcpSocket(this))
	{
		connect(m_tcpSocket, &QTcpSocket::stateChanged, this, &TcpClient::slotTcpSocketStateChange);
	}

	TcpClient::~TcpClient()
	{
		if (m_tcpSocket != NULL)
		{
			m_tcpSocket->close();
			delete m_tcpSocket;
			m_tcpSocket = NULL;
		}
	}

	QTcpSocket *TcpClient::getTcpSocket()
	{
		return m_tcpSocket;
	}

	bool TcpClient::connectToServer(int localPort, QString strTargetIp, int targetPort, const int retryTimes)
	{
		if (localPort < 0 || localPort > USHRT_MAX || strTargetIp.isEmpty() || targetPort < 0 || targetPort > USHRT_MAX)
		{
			qDebug() << "NETWORK OVER LIMIT OR EMPTY";
			return false;
		}

		m_tcpSocket->setProxy(QNetworkProxy::NoProxy);

		bool t_bind = m_tcpSocket->bind(QHostAddress::LocalHost, localPort, QTcpSocket::ReuseAddressHint);
		if (!t_bind)
		{
			qDebug() << "BINDING FAILURE";
			return false;
		}

		int index = 0;
		bool ret = false;
		do
		{
			m_tcpSocket->connectToHost(strTargetIp, targetPort);
			ret = m_tcpSocket->waitForConnected(1000);
		} while (!ret && ++index < retryTimes);

		return ret;
	}

	bool TcpClient::connectToServer(QString strTargetIp, int targetPort, const int retryTimes)
	{
		if (strTargetIp.isEmpty() || targetPort < 0 || targetPort > USHRT_MAX)
		{
			return false;
		}

		m_tcpSocket->setProxy(QNetworkProxy::NoProxy);
		int index = 0;
		bool ret = false;
		do
		{
			m_tcpSocket->connectToHost(strTargetIp, targetPort);
			ret = m_tcpSocket->waitForConnected(1000);
		} while (!ret && ++index < retryTimes);

		return ret;
	}

	bool TcpClient::disconnectFromServer()
	{
		if (m_tcpSocket == nullptr)
		{
			return false;
		}

		m_tcpSocket->disconnectFromHost();
		if (m_tcpSocket->state() == QAbstractSocket::UnconnectedState || m_tcpSocket->waitForDisconnected(1000))
		{
			return true;
		}
		return false;
	}

	bool TcpClient::isConnected()
	{
		if (m_tcpSocket == nullptr)
		{
			return false;
		}

		return m_tcpSocket->state() == QAbstractSocket::ConnectedState;
	}

	bool TcpClient::sendTcpMsg(QByteArray message)
	{
		if (!isConnected())
		{
			return false;
		}

		m_tcpSocket->readAll();
		m_tcpSocket->write(message);
		return m_tcpSocket->flush();
	}

	bool TcpClient::recvTcpMsg(QByteArray &message, const int replyTime)
	{
		if (!isConnected())
		{
			return false;
		}

		if (m_tcpSocket->waitForReadyRead(replyTime))
		{
			QByteArray data = m_tcpSocket->readAll();
			message.append(data);
			return true;
		}
		return false;
	}

	bool TcpClient::sendAndRecvTcpMsg(const QByteArray sendMsg, QByteArray &recvMsg, const int replyTime)
	{
		if (!isConnected())
		{
			return false;
		}

		if (sendTcpMsg(sendMsg))
		{
			bool ret = recvTcpMsg(recvMsg, replyTime);
			return ret;
		}
		return false;
	}

	void TcpClient::clear()
	{
		if (m_tcpSocket != NULL)
		{
			m_tcpSocket->readAll();
		}
	}

	void TcpClient::slotTcpSocketStateChange(QAbstractSocket::SocketState state)
	{
		switch (state)
		{
			//[] socket 未连接
		case QAbstractSocket::UnconnectedState:
		{
			qDebug() << "QAbstractSocket::UnconnectedState";
			break;
		}
		//[]套接字正在执行主机名查找。
		case QAbstractSocket::HostLookupState:
		{
			qDebug() << "QAbstractSocket::HostLookupState";
			break;
		}
		//[]  套接字已开始建立连接。
		case QAbstractSocket::ConnectingState:
		{
			qDebug() << "QAbstractSocket::ConnectingState";
			break;
		}
		//[] 建立连接
		case QAbstractSocket::ConnectedState:
		{
			qDebug() << "QAbstractSocket::ConnectedState";
			break;
		}
		//[]  套接字绑定到一个地址和端口
		case QAbstractSocket::BoundState:
		{
			qDebug() << "QAbstractSocket::BoundState";
			break;
		}
		//[] 套接字即将关闭
		case QAbstractSocket::ClosingState:
		{
			qDebug() << "QAbstractSocket::ClosingState";
			break;
		}
		//[] 监听状态
		case QAbstractSocket::ListeningState:
		{
			qDebug() << "QAbstractSocket::ListeningState";
			break;
		}
		default:
			break;
		}
	}

} //namespace Core
